package cn.com.dmg.myspringboot.file.pdf;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageXYZDestination;

/***
 *  合并pdf文件，并添加目录
 */
public class PDFMergerWithTOC {

    public static void main(String[] args) {

        List<String> sourceFiles = new ArrayList<>();
        sourceFiles.add("D:\\opt\\shth\\alcertificatemode\\h1.pdf");
        sourceFiles.add("D:\\opt\\shth\\alcertificatemode\\h2.pdf");
        sourceFiles.add("D:\\opt\\shth\\alcertificatemode\\h3.pdf");
        mergePdf(sourceFiles, "D:\\opt\\shth\\alcertificatemode\\hj2.pdf", false);


//        List<Map<String, String>> sourceMapFiles = new ArrayList<>();
//        Map<String, String> map1 = new HashMap<>();
//        map1.put("name","ceshi1");
//        map1.put("url","D:\\opt\\shth\\alcertificatemode\\h1.pdf");
//        sourceMapFiles.add(map1);
//        Map<String, String> map2 = new HashMap<>();
//        map2.put("name","ceshi2");
//        map2.put("url","D:\\opt\\shth\\alcertificatemode\\h2.pdf");
//        sourceMapFiles.add(map2);
//        Map<String, String> map3 = new HashMap<>();
//        map3.put("name","ceshi3");
//        map3.put("url","D:\\opt\\shth\\alcertificatemode\\h3.pdf");
//        sourceMapFiles.add(map3);
//
//        mergePdf2(sourceMapFiles, "D:\\opt\\shth\\alcertificatemode\\hj3.pdf", true);
    }

    /**
     * 多个pdf文件合并成一个文件
     * 生成目录功能还得优化，不能完全使用。且生成以后再最后一页
     *
     * @param sourceFiles 原来文件地址
     * @param outFile     合并文件存放地址
     * @param bool        是否添加目录
     * @return boolean
     */
    public static boolean mergePdf(List<String> sourceFiles, String outFile, boolean bool) {
        boolean isSuccess = true;
        try {
            // 创建一个PDFMergerUtility实例
            PDFMergerUtility merger = new PDFMergerUtility();
            // 设置合并后的PDF文件路径
            merger.setDestinationFileName(outFile);
            // 添加要合并的PDF文件
            for (String sourceFile : sourceFiles) {
                merger.addSource(new File(sourceFile));
            }
            // 合并PDF文件
            merger.mergeDocuments(null);

            //如果是false 将不会生成目录，
            if (!bool) {
                return isSuccess;
            }


            // 打开合并后的PDF文件以添加目录
            PDDocument doc = PDDocument.load(new File(outFile));
            // 创建一个新页面用于目录
            PDPage tocPage = new PDPage();
            doc.addPage(tocPage);

            // 开始写入目录内容
            PDPageContentStream contentStream = new PDPageContentStream(doc, tocPage);
            contentStream.beginText();
            contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
            contentStream.newLineAtOffset(25, 700);
            contentStream.showText("mulu");
            contentStream.newLineAtOffset(0, -15);

            for (String sourceFile : sourceFiles) {
                PDDocument docxx = PDDocument.load(new File(sourceFile));
                docxx.getNumberOfPages();

            }
            contentStream.setFont(PDType1Font.HELVETICA, 10);
            contentStream.showText("1");
            contentStream.newLineAtOffset(0, -15);
            contentStream.showText("2");
            // ... 添加其他目录项
            contentStream.endText();
            contentStream.close();

            // 保存带有目录的合并后的PDF文件
            doc.save(outFile);
            doc.close();
            return isSuccess;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 添加目录索引失败-此方法请勿使用
     * @param sourceFiles
     * @param outFile
     * @param bool
     * @return
     */
    public static boolean mergePdf2(List<Map<String, String>> sourceFiles,String outFile,boolean bool) {
        try {
            // 创建一个PDFMergerUtility实例
            PDFMergerUtility merger = new PDFMergerUtility();
            // 设置合并后的PDF文件路径
            merger.setDestinationFileName(outFile);
            // 添加要合并的PDF文件
            for (int i = 0; i < sourceFiles.size(); i++) {
                Map<String, String> map = sourceFiles.get(i);
                String s = map.get("url");
                System.out.println("s = " + s);
                merger.addSource(new File(s));
            }
            // 合并PDF文件
            merger.mergeDocuments(null);

            if (!bool) {
                return true;
            }
            // 打开合并后的PDF文件以添加目录
            PDDocument doc = PDDocument.load(new File(outFile));

            // 添加目录页
            PDPage tocPage = new PDPage();
            doc.addPage(tocPage);

            PDPageContentStream contentStream = new PDPageContentStream(doc, tocPage);
            contentStream.beginText();

            // 设置目录项的位置和大小
            float yPosition = 700; // 初始Y位置
            float textX = 50;
            float linkRectWidth = 200; // 目录项链接矩形的宽度
            float linkRectHeight = 15; // 目录项链接矩形的高度

            // 假设的页面跳转映射
            Map<String, Integer> pageNumbers = new HashMap<>();

            //处理
            int num = 1;
            for (Map<String, String> map : sourceFiles) {
                String s = map.get("url");
                String name = map.get("name");
                PDDocument docNumber = PDDocument.load(new File(s));
                int numberOfPages = docNumber.getNumberOfPages();
                pageNumbers.put(name,num);
                num = num + numberOfPages;
            }
            // 遍历章节并添加链接
            for (Map.Entry<String, Integer> entry : pageNumbers.entrySet()) {
                String title = entry.getKey();
                int pageNumber = entry.getValue();

                // 绘制章节标题文本
//                contentStream.beginText();
                contentStream.setFont(PDType1Font.HELVETICA, 10);
                contentStream.newLineAtOffset(textX, yPosition);
                contentStream.showText(title);
                contentStream.endText();

                // 计算链接矩形的位置和大小
                PDRectangle linkRect = new PDRectangle(textX, yPosition - linkRectHeight / 2, linkRectWidth, linkRectHeight);

                // 创建目标位置
                PDPageDestination pageDestination = new PDPageXYZDestination();
                pageDestination.setPageNumber(pageNumber);

                // 创建动作
                PDActionGoTo action = new PDActionGoTo();
                action.setDestination(pageDestination);

                // 创建链接注解并设置动作
                PDAnnotationLink link = new PDAnnotationLink();
                link.setRectangle(linkRect);
                link.setAction(action);
                link.setPage(tocPage);

                // 将链接添加到页面中
                tocPage.getAnnotations().add(link);

                // 移动到下一个目录项的位置
                yPosition -= linkRectHeight + 5; // 加上一些间距
            }

            contentStream.close();

            // 保存文档
            doc.save(outFile);
            doc.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}
